/**
 * Copyright 2007-2010 非也
 * All rights reserved. 
 * 
 * This library is free software; you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License v3 as published by the Free Software
 * Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along
 * with this library; if not, see http://www.gnu.org/licenses/lgpl.html.
 *
 */
package org.fireflow2.designer.eclipse.properties.common;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.xml.namespace.QName;

import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.TrayDialog;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.jface.viewers.TreeSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.fireflow.engine.WorkflowSession;
import org.fireflow.engine.context.RuntimeContext;
import org.fireflow.engine.entity.runtime.ActivityInstance;
import org.fireflow.engine.entity.runtime.ProcessInstance;
import org.fireflow.engine.modules.script.ScriptContextVariableNames;
import org.fireflow.model.data.Expression;
import org.fireflow.model.data.impl.ExpressionImpl;
import org.fireflow2.designer.eclipse.modelwrapper.SubProcessWrapper;
import org.fireflow2.designer.eclipse.modelwrapper.Wrapper;
import org.fireflow2.designer.eclipse.modelwrapper.basic.DataFieldWrapper;
import org.fireflow2.designer.eclipse.modelwrapper.collection.DataFieldListWrapper;
import org.firesoa.common.schema.NameSpaces;
import org.firesoa.common.util.ScriptLanguages;

/**
 * 
 * @author 非也 nychen2000@163.com Fire Workflow 官方网站：www.firesoa.com 或者
 *         www.fireflow.org
 * 
 */
public class XPathExpressionEditDialog extends TrayDialog {
	private static XPathNode XPATH_NODE_RUNTIME_CONTEXT = null;
	private static XPathNode XPATH_NODE_CURRENT_PROCESS_INSTANCE = null;
	private static XPathNode XPATH_NODE_CURRENT_ACTIVITY_INSTANCE = null;
	private static XPathNode XPATH_NODE_WORKFLOW_SESSION = null;
	private static XPathNode XPATH_NODE_PROCESS_VARIABLES = null;
	private static XPathNode XPATH_NODE_ACTIVITY_VARIABLES = null;
	
	static {
		XPATH_NODE_RUNTIME_CONTEXT = new XPathNode(ScriptContextVariableNames.RUNTIME_CONTEXT,"Fire workflow RuntimeContext",
				true,new QName(NameSpaces.JAVA.getUri(),RuntimeContext.class.getName(),NameSpaces.JAVA.getPrefix()));

		XPATH_NODE_WORKFLOW_SESSION = new XPathNode(ScriptContextVariableNames.WORKFLOW_SESSION,"Fire workflow Session",
				true,new QName(NameSpaces.JAVA.getUri(),WorkflowSession.class.getName(),NameSpaces.JAVA.getPrefix()));

		XPATH_NODE_PROCESS_VARIABLES = new XPathNode(ScriptContextVariableNames.PROCESS_VARIABLES,"流程变量",
				false,new QName(NameSpaces.JAVA.getUri(),Map.class.getName(),NameSpaces.JAVA.getPrefix()));

		XPATH_NODE_ACTIVITY_VARIABLES = new XPathNode(ScriptContextVariableNames.ACTIVITY_VARIABLES,"活动局部变量",
				false,new QName(NameSpaces.JAVA.getUri(),Map.class.getName(),NameSpaces.JAVA.getPrefix()));

		//流程实例及下属节点
		XPATH_NODE_CURRENT_PROCESS_INSTANCE = new XPathNode(ScriptContextVariableNames.CURRENT_PROCESS_INSTANCE,"当前流程实例",
				true,new QName(NameSpaces.JAVA.getUri(),ProcessInstance.class.getName(),NameSpaces.JAVA.getPrefix()));
		
		XPathNode xpathNode = new XPathNode("id","流程实例id",
				true,new QName(NameSpaces.JAVA.getUri(),String.class.getName(),NameSpaces.JAVA.getPrefix()));
		XPATH_NODE_CURRENT_PROCESS_INSTANCE.addChild(xpathNode);
		
		xpathNode = new XPathNode("bizId","流程实例所关联的业务主键",
				true,new QName(NameSpaces.JAVA.getUri(),String.class.getName(),NameSpaces.JAVA.getPrefix()));
		XPATH_NODE_CURRENT_PROCESS_INSTANCE.addChild(xpathNode);
	
		xpathNode = new XPathNode("bizType","业务类型",
				true,new QName(NameSpaces.JAVA.getUri(),String.class.getName(),NameSpaces.JAVA.getPrefix()));
		XPATH_NODE_CURRENT_PROCESS_INSTANCE.addChild(xpathNode);
		
		xpathNode = new XPathNode("processId","流程Id",
				true,new QName(NameSpaces.JAVA.getUri(),String.class.getName(),NameSpaces.JAVA.getPrefix()));
		XPATH_NODE_CURRENT_PROCESS_INSTANCE.addChild(xpathNode);
		
		xpathNode = new XPathNode("version","流程版本号",
				true,new QName(NameSpaces.JAVA.getUri(),Integer.class.getName(),NameSpaces.JAVA.getPrefix()));
		XPATH_NODE_CURRENT_PROCESS_INSTANCE.addChild(xpathNode);
		
		xpathNode = new XPathNode("processName","流程名称",
				true,new QName(NameSpaces.JAVA.getUri(),String.class.getName(),NameSpaces.JAVA.getPrefix()));
		XPATH_NODE_CURRENT_PROCESS_INSTANCE.addChild(xpathNode);
		
		xpathNode = new XPathNode("subProcessId","子流程Id",
				true,new QName(NameSpaces.JAVA.getUri(),String.class.getName(),NameSpaces.JAVA.getPrefix()));
		XPATH_NODE_CURRENT_PROCESS_INSTANCE.addChild(xpathNode);
		
		xpathNode = new XPathNode("subProcessName","子流程名称",
				true,new QName(NameSpaces.JAVA.getUri(),String.class.getName(),NameSpaces.JAVA.getPrefix()));
		XPATH_NODE_CURRENT_PROCESS_INSTANCE.addChild(xpathNode);
		
		xpathNode = new XPathNode("creatorId","实例创建者Id",
				true,new QName(NameSpaces.JAVA.getUri(),String.class.getName(),NameSpaces.JAVA.getPrefix()));
		XPATH_NODE_CURRENT_PROCESS_INSTANCE.addChild(xpathNode);
		
		xpathNode = new XPathNode("creatorName","实例创建者姓名",
				true,new QName(NameSpaces.JAVA.getUri(),String.class.getName(),NameSpaces.JAVA.getPrefix()));
		XPATH_NODE_CURRENT_PROCESS_INSTANCE.addChild(xpathNode);
		
		xpathNode = new XPathNode("creatorDeptId","实例创建者部门Id",
				true,new QName(NameSpaces.JAVA.getUri(),String.class.getName(),NameSpaces.JAVA.getPrefix()));
		XPATH_NODE_CURRENT_PROCESS_INSTANCE.addChild(xpathNode);
		
		xpathNode = new XPathNode("creatorDeptName","实例创建者部门名称",
				true,new QName(NameSpaces.JAVA.getUri(),String.class.getName(),NameSpaces.JAVA.getPrefix()));
		XPATH_NODE_CURRENT_PROCESS_INSTANCE.addChild(xpathNode);
		
		xpathNode = new XPathNode("createdTime","实例创建时间",
				true,new QName(NameSpaces.JAVA.getUri(),Date.class.getName(),NameSpaces.JAVA.getPrefix()));
		XPATH_NODE_CURRENT_PROCESS_INSTANCE.addChild(xpathNode);
		
		xpathNode = new XPathNode("expiredTime","到期时间",
				true,new QName(NameSpaces.JAVA.getUri(),Date.class.getName(),NameSpaces.JAVA.getPrefix()));
		XPATH_NODE_CURRENT_PROCESS_INSTANCE.addChild(xpathNode);
		
		xpathNode = new XPathNode("endTime","结束时间",
				true,new QName(NameSpaces.JAVA.getUri(),Date.class.getName(),NameSpaces.JAVA.getPrefix()));
		XPATH_NODE_CURRENT_PROCESS_INSTANCE.addChild(xpathNode);
		
		xpathNode = new XPathNode("state","实例状态",
				true,new QName(NameSpaces.JAVA.getUri(),Integer.class.getName(),NameSpaces.JAVA.getPrefix()));
		XPATH_NODE_CURRENT_PROCESS_INSTANCE.addChild(xpathNode);
		
		xpathNode = new XPathNode("suspended","是否挂起",
				true,new QName(NameSpaces.JAVA.getUri(),Boolean.class.getName(),NameSpaces.JAVA.getPrefix()));
		XPATH_NODE_CURRENT_PROCESS_INSTANCE.addChild(xpathNode);
		
		//活动实例及下属节点
		XPATH_NODE_CURRENT_ACTIVITY_INSTANCE = new XPathNode(ScriptContextVariableNames.CURRENT_ACTIVITY_INSTANCE,"当前活动实例",
				true,new QName(NameSpaces.JAVA.getUri(),ActivityInstance.class.getName(),NameSpaces.JAVA.getPrefix()));
		
		xpathNode = new XPathNode("id","活动实例id",
				true,new QName(NameSpaces.JAVA.getUri(),String.class.getName(),NameSpaces.JAVA.getPrefix()));
		XPATH_NODE_CURRENT_ACTIVITY_INSTANCE.addChild(xpathNode);
		
		xpathNode = new XPathNode("nodeId","活动id",
				true,new QName(NameSpaces.JAVA.getUri(),String.class.getName(),NameSpaces.JAVA.getPrefix()));
		XPATH_NODE_CURRENT_ACTIVITY_INSTANCE.addChild(xpathNode);
		
		xpathNode = new XPathNode("name","活动名称",
				true,new QName(NameSpaces.JAVA.getUri(),String.class.getName(),NameSpaces.JAVA.getPrefix()));
		XPATH_NODE_CURRENT_ACTIVITY_INSTANCE.addChild(xpathNode);
		
		xpathNode = new XPathNode("displayName","活动中文名称",
				true,new QName(NameSpaces.JAVA.getUri(),String.class.getName(),NameSpaces.JAVA.getPrefix()));
		XPATH_NODE_CURRENT_ACTIVITY_INSTANCE.addChild(xpathNode);
		
		xpathNode = new XPathNode("serviceId","绑定的服务Id",
				true,new QName(NameSpaces.JAVA.getUri(),String.class.getName(),NameSpaces.JAVA.getPrefix()));
		XPATH_NODE_CURRENT_ACTIVITY_INSTANCE.addChild(xpathNode);
//		xpathNode = new XPathNode("bizId","流程实例所关联的业务主键",
//				true,new QName(NameSpaces.JAVA.getUri(),String.class.getName(),NameSpaces.JAVA.getPrefix()));
//		XPATH_NODE_CURRENT_ACTIVITY_INSTANCE.addChild(xpathNode);
//	
//		xpathNode = new XPathNode("bizType","业务类型",
//				true,new QName(NameSpaces.JAVA.getUri(),String.class.getName(),NameSpaces.JAVA.getPrefix()));
//		XPATH_NODE_CURRENT_ACTIVITY_INSTANCE.addChild(xpathNode);
//		
//		xpathNode = new XPathNode("processId","流程Id",
//				true,new QName(NameSpaces.JAVA.getUri(),String.class.getName(),NameSpaces.JAVA.getPrefix()));
//		XPATH_NODE_CURRENT_ACTIVITY_INSTANCE.addChild(xpathNode);
//		
//		xpathNode = new XPathNode("version","流程版本号",
//				true,new QName(NameSpaces.JAVA.getUri(),Integer.class.getName(),NameSpaces.JAVA.getPrefix()));
//		XPATH_NODE_CURRENT_ACTIVITY_INSTANCE.addChild(xpathNode);
//		
//		xpathNode = new XPathNode("processName","流程名称",
//				true,new QName(NameSpaces.JAVA.getUri(),String.class.getName(),NameSpaces.JAVA.getPrefix()));
//		XPATH_NODE_CURRENT_ACTIVITY_INSTANCE.addChild(xpathNode);
//		
//		xpathNode = new XPathNode("subProcessId","子流程Id",
//				true,new QName(NameSpaces.JAVA.getUri(),String.class.getName(),NameSpaces.JAVA.getPrefix()));
//		XPATH_NODE_CURRENT_ACTIVITY_INSTANCE.addChild(xpathNode);
//		
//		xpathNode = new XPathNode("subProcessName","子流程名称",
//				true,new QName(NameSpaces.JAVA.getUri(),String.class.getName(),NameSpaces.JAVA.getPrefix()));
//		XPATH_NODE_CURRENT_ACTIVITY_INSTANCE.addChild(xpathNode);
//		
//		xpathNode = new XPathNode("creatorId","实例创建者Id",
//				true,new QName(NameSpaces.JAVA.getUri(),String.class.getName(),NameSpaces.JAVA.getPrefix()));
//		XPATH_NODE_CURRENT_ACTIVITY_INSTANCE.addChild(xpathNode);
//		
//		xpathNode = new XPathNode("creatorName","实例创建者姓名",
//				true,new QName(NameSpaces.JAVA.getUri(),String.class.getName(),NameSpaces.JAVA.getPrefix()));
//		XPATH_NODE_CURRENT_ACTIVITY_INSTANCE.addChild(xpathNode);
//		
//		xpathNode = new XPathNode("creatorDeptId","实例创建者部门Id",
//				true,new QName(NameSpaces.JAVA.getUri(),String.class.getName(),NameSpaces.JAVA.getPrefix()));
//		XPATH_NODE_CURRENT_ACTIVITY_INSTANCE.addChild(xpathNode);
//		
//		xpathNode = new XPathNode("creatorDeptName","实例创建者部门名称",
//				true,new QName(NameSpaces.JAVA.getUri(),String.class.getName(),NameSpaces.JAVA.getPrefix()));
//		XPATH_NODE_CURRENT_ACTIVITY_INSTANCE.addChild(xpathNode);
		
		xpathNode = new XPathNode("createdTime","实例创建时间",
				true,new QName(NameSpaces.JAVA.getUri(),Date.class.getName(),NameSpaces.JAVA.getPrefix()));
		XPATH_NODE_CURRENT_ACTIVITY_INSTANCE.addChild(xpathNode);
		
		xpathNode = new XPathNode("expiredTime","到期时间",
				true,new QName(NameSpaces.JAVA.getUri(),Date.class.getName(),NameSpaces.JAVA.getPrefix()));
		XPATH_NODE_CURRENT_ACTIVITY_INSTANCE.addChild(xpathNode);
		
		xpathNode = new XPathNode("endTime","结束时间",
				true,new QName(NameSpaces.JAVA.getUri(),Date.class.getName(),NameSpaces.JAVA.getPrefix()));
		XPATH_NODE_CURRENT_ACTIVITY_INSTANCE.addChild(xpathNode);
		
		xpathNode = new XPathNode("state","实例状态",
				true,new QName(NameSpaces.JAVA.getUri(),Integer.class.getName(),NameSpaces.JAVA.getPrefix()));
		XPATH_NODE_CURRENT_ACTIVITY_INSTANCE.addChild(xpathNode);
		
		xpathNode = new XPathNode("suspended","是否挂起",
				true,new QName(NameSpaces.JAVA.getUri(),Boolean.class.getName(),NameSpaces.JAVA.getPrefix()));
		XPATH_NODE_CURRENT_ACTIVITY_INSTANCE.addChild(xpathNode);
		
		
	}

	SubProcessWrapper subProcessWrapper = null;
	Expression jxpathExpression = null;
	private boolean isFromExpression = true;
	TreeViewer propertiesListViewer = null;
	
	Text expressionBody  = null;
	Text dataType = null;
	Text expressionName = null;

	public Expression getExpression(){
		return jxpathExpression;
	}
	
	public void setExpression(Expression exp){
		jxpathExpression = exp;
	}
	/**
	 * @param parent
	 */
	public XPathExpressionEditDialog(Shell parent,
			SubProcessWrapper subProcessWrapper,boolean isFromExpression) {
		super(parent);
		setShellStyle(getShellStyle() | SWT.RESIZE | SWT.MAX | SWT.TITLE);
		this.subProcessWrapper = subProcessWrapper;
		
		this.isFromExpression = isFromExpression;
		jxpathExpression = new ExpressionImpl();
		((ExpressionImpl)jxpathExpression).setLanguage(ScriptLanguages.XPATH.name());
		
		
	}

	protected Control createDialogArea(final Composite parent) {
		Composite container = (Composite) super.createDialogArea(parent);

		FormToolkit formToolkit = new FormToolkit(Display.getCurrent());

		container.setLayout(new GridLayout(1, false));

		org.eclipse.swt.widgets.Group propertiesListGroup = new org.eclipse.swt.widgets.Group(container,SWT.None);
		GridData gridData = new GridData(GridData.FILL_BOTH);
		propertiesListGroup.setLayout(new GridLayout(1,false));
		
		propertiesListGroup.setLayoutData(gridData);
		//		Label lb = new Label(container, SWT.NULL);
		propertiesListGroup.setText("待选变量列表：");


		propertiesListViewer = new TreeViewer(propertiesListGroup, SWT.SINGLE
				| SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
		GridData gridData2 = new GridData(GridData.FILL_BOTH);
		propertiesListViewer.getControl().setLayoutData(gridData2);
		propertiesListViewer.setLabelProvider(new LabelProvider(){
			public String getText(Object element) {
				if (element instanceof XPathNode){
					XPathNode prop = (XPathNode)element;
					return prop.getName();
				}
				return element == null ? "" : element.toString();//$NON-NLS-1$
			}
		});
		
		propertiesListViewer.setContentProvider(new PropertiesTreeContententProvider(isFromExpression));
		propertiesListViewer.setInput(subProcessWrapper);
		propertiesListViewer.addSelectionChangedListener(new ISelectionChangedListener(){

			public void selectionChanged(SelectionChangedEvent event) {
				ISelection selection = event.getSelection();
				if (selection instanceof TreeSelection){
					TreeSelection tselection = (TreeSelection)selection;
					handleSelectionChanged(tselection);
				}
				
			}
			
		});
		propertiesListViewer.addDoubleClickListener(new IDoubleClickListener(){

			public void doubleClick(DoubleClickEvent event) {
				// TODO Auto-generated method stub
				
			}
			
		});
		
		
		final Tree tree = (Tree)propertiesListViewer.getControl();
		
		final Listener labelListener = new Listener () {
			public void handleEvent (Event event) {
				Label label = (Label)event.widget;
				Shell shell = label.getShell ();
				switch (event.type) {
					case SWT.MouseDown:
						Event e = new Event ();
						e.item = (TreeItem) label.getData ("_TABLEITEM");
						// Assuming table is single select, set the selection as if
						// the mouse down event went through to the table
						tree.setSelection (new TreeItem [] {(TreeItem) e.item});
						tree.notifyListeners (SWT.Selection, e);
						shell.dispose ();
						tree.setFocus();
						break;
					case SWT.MouseExit:
						shell.dispose ();
						break;
				}
			}
		};
		
		Listener treeListener = new Listener () {
			Shell tip = null;
			Label label = null;
			public void handleEvent (Event event) {
				switch (event.type) {
					case SWT.Dispose:
					case SWT.KeyDown:
					case SWT.MouseMove: {
						if (tip == null) break;
						tip.dispose ();
						tip = null;
						label = null;
						break;
					}
					case SWT.MouseHover: {
						TreeItem item = tree.getItem (new Point (event.x, event.y));
						
						if (item != null) {
							XPathNode data = (XPathNode)item.getData();
							if (tip != null  && !tip.isDisposed ()) tip.dispose ();
							tip = new Shell (parent.getShell(), SWT.ON_TOP | SWT.NO_FOCUS | SWT.TOOL);
							tip.setBackground (parent.getDisplay().getSystemColor (SWT.COLOR_INFO_BACKGROUND));
							FillLayout layout = new FillLayout ();
							layout.marginWidth = 2;
							tip.setLayout (layout);
							label = new Label (tip, SWT.NONE);
							label.setForeground (parent.getDisplay().getSystemColor (SWT.COLOR_INFO_FOREGROUND));
							label.setBackground (parent.getDisplay().getSystemColor (SWT.COLOR_INFO_BACKGROUND));
							label.setData ("_TABLEITEM", item);
							label.setText (data.getDisplayName());
							label.addListener (SWT.MouseExit, labelListener);
							label.addListener (SWT.MouseDown, labelListener);
							Point size = tip.computeSize (SWT.DEFAULT, SWT.DEFAULT);
							Rectangle rect = item.getBounds (0);
							Point pt = tree.toDisplay (rect.x+rect.width+1, rect.y);
							tip.setBounds (pt.x, pt.y, size.x, size.y);
							tip.setVisible (true);
						}
					}
				}
			}
		};
		
		tree.addListener (SWT.Dispose, treeListener);
		tree.addListener (SWT.KeyDown, treeListener);
		tree.addListener (SWT.MouseMove, treeListener);
		tree.addListener (SWT.MouseHover, treeListener);
		
		org.eclipse.swt.widgets.Group expressionGroup = new org.eclipse.swt.widgets.Group(container,SWT.None);
		expressionGroup.setText("表达式：");
		GridData gridData3 = new GridData(GridData.FILL_BOTH);
		expressionGroup.setLayoutData(gridData3);
		expressionGroup.setLayout(new GridLayout(3,false));
		
		Label lb = new Label(expressionGroup,SWT.None);
		lb.setText("JXpath表达式：");
		
		expressionBody = formToolkit.createText(expressionGroup, "");
		gridData = new GridData(GridData.FILL_HORIZONTAL);
		gridData.horizontalSpan = 2;
		expressionBody.setLayoutData(gridData);
		
		lb = new Label(expressionGroup,SWT.None);
		lb.setText("数据类型：");
		
		dataType = formToolkit.createText(expressionGroup, "");
		gridData = new GridData(GridData.FILL_HORIZONTAL);
		dataType.setLayoutData(gridData);
		
		Button button = new Button(expressionGroup,SWT.None);
		button.setText("...");
		button.addSelectionListener(new SelectionAdapter(){
			
		});

		lb = new Label(expressionGroup,SWT.None);
		lb.setText("名称：");
		
		expressionName = formToolkit.createText(expressionGroup, "");
		gridData = new GridData(GridData.FILL_HORIZONTAL);
		gridData.horizontalSpan = 2;
		expressionName.setLayoutData(gridData);
		
		return container;
		
	}
	
	protected void refresh(){
		expressionBody.setText(jxpathExpression.getBody());
		dataType.setText(jxpathExpression.getDataType()==null?"":jxpathExpression.getDataType().getPrefix()+":"+jxpathExpression.getDataType().getLocalPart());
		expressionName.setText(jxpathExpression.getName());
		
		//计算okbutton的状态。
		if (isFromExpression){
			String expressionName = jxpathExpression.getName();
			if (expressionName==null || 
					expressionName.equals(ScriptContextVariableNames.SESSION_ATTRIBUTES)||
					expressionName.equals(ScriptContextVariableNames.PROCESS_VARIABLES) ||
					expressionName.equals(ScriptContextVariableNames.ACTIVITY_VARIABLES)){
				Button button = this.getButton(IDialogConstants.OK_ID);
				button.setEnabled(false);
			}
			else {
				Button button = this.getButton(IDialogConstants.OK_ID);
				button.setEnabled(true);
			}
		}else{//toExpression
			String expressionName = jxpathExpression.getName();
			if (expressionName==null || 
					expressionName.equals(ScriptContextVariableNames.SESSION_ATTRIBUTES)||
					expressionName.equals(ScriptContextVariableNames.PROCESS_VARIABLES) ||
					expressionName.equals(ScriptContextVariableNames.ACTIVITY_VARIABLES)){
				Button button = this.getButton(IDialogConstants.OK_ID);
				button.setEnabled(false);
			}
			else {
				Button button = this.getButton(IDialogConstants.OK_ID);
				button.setEnabled(true);
			}
		}
	}
	
	protected void handleSelectionChanged(TreeSelection treeSelection){
		TreePath[] paths = treeSelection.getPaths();
		if (paths==null || paths.length==0){
			refresh();
			return;
		}

		StringBuffer bodyBuf = new StringBuffer();
		StringBuffer displayNameBuf = new StringBuffer();
		TreePath path = paths[0];
		int count = path.getSegmentCount();
		String name = "";
		QName dataType = null;
		for (int i=0;i<count;i++){
			XPathNode segment = (XPathNode)path.getSegment(i);
			name = segment.getName();
			String displayName = segment.getDisplayName();
			dataType = segment.getDataType();

			bodyBuf.append(name);
			displayNameBuf.append(displayName);
			if (i<count-1){
				bodyBuf.append("/");
				displayNameBuf.append("/");
			}
		}

		((ExpressionImpl)jxpathExpression).setBody(bodyBuf.toString());
		jxpathExpression.setDisplayName(displayNameBuf.toString());
		jxpathExpression.setName(name);
		jxpathExpression.setDataType(dataType);
		
		refresh();
	}

	protected Rectangle cachedBounds;

	protected Point getInitialSize() {
		return new Point(400,300);
//		// Track the current dialog bounds.
//		getShell().addControlListener(new ControlListener() {
//			public void controlMoved(ControlEvent arg0) {
//				cachedBounds = getShell().getBounds();
//			}
//
//			public void controlResized(ControlEvent arg0) {
//				cachedBounds = getShell().getBounds();
//			}
//		});
//
//		// Answer the size from the previous incarnation.
//		Rectangle b1 = getShell().getDisplay().getBounds();
//		Rectangle b2 = loadBounds();
//		if (b2 != null)
//			return new Point(b1.width < b2.width ? b1.width : b2.width,
//					b1.height < b1.height ? b2.height : b2.height);
//
//		return super.getInitialSize();
	}

	protected Point getInitialLocation(Point initialSize) {

		// Answer the location from the previous incarnation.
//		Rectangle displayBounds = getShell().getDisplay().getBounds();
//		Rectangle bounds = loadBounds();
//		if (bounds != null) {
//			int x = bounds.x;
//			int y = bounds.y;
//			int maxX = displayBounds.x + displayBounds.width - initialSize.x;
//			int maxY = displayBounds.y + displayBounds.height - initialSize.y;
//			if (x > maxX)
//				x = maxX;
//			if (y > maxY)
//				y = maxY;
//			if (x < displayBounds.x)
//				x = displayBounds.x;
//			if (y < displayBounds.y)
//				y = displayBounds.y;
//			return new Point(x, y);
//		}
		return super.getInitialLocation(initialSize);
	}

	private static final String TAG_X = "x";
	private static final String TAG_Y = "y";
	private static final String TAG_WIDTH = "width";
	private static final String TAG_HEIGHT = "height";

	private Rectangle loadBounds() {
		return new Rectangle(0,0,400,300);
		//TODO this.getDialogBoundsSettings()返回空，暂时屏蔽
//		IDialogSettings settings = this.getDialogBoundsSettings();
//		try {
//			return new Rectangle(settings.getInt(TAG_X),
//					settings.getInt(TAG_Y), settings.getInt(TAG_WIDTH),
//					settings.getInt(TAG_HEIGHT));
//		} catch (NumberFormatException e) {
//			return null;
//		}
	}

	private void saveBounds(Rectangle bounds) {
		//TODO this.getDialogBoundsSettings()返回空，暂时屏蔽
//		IDialogSettings settings = this.getDialogBoundsSettings();
//		settings.put(TAG_X, bounds.x);
//		settings.put(TAG_Y, bounds.y);
//		settings.put(TAG_WIDTH, bounds.width);
//		settings.put(TAG_HEIGHT, bounds.height);
	}

	public boolean close() {
		boolean closed = super.close();
		if (closed && cachedBounds != null)
			saveBounds(cachedBounds);
		return closed;
	}

	protected void configureShell(Shell newShell) {
		super.configureShell(newShell);
		newShell.setText("编辑JXpath表达式");
	}

	/**
	 * 构成xpath的节点
	 *
	 * @author 非也 nychen2000@163.com
	 * Fire Workflow 官方网站：www.firesoa.com 或者 www.fireflow.org
	 *
	 */
	static class  XPathNode {
		String name;
		String displayName;
		QName dataType;
		Boolean canBeSelected;//是否可被选择
		List<XPathNode> children = new ArrayList<XPathNode>();
		XPathNode parent = null;
		
		public XPathNode(){
			
		}
		
		public XPathNode(String nm,String dispName,boolean b,QName dType){
			this.name = nm;
			this.displayName = dispName;
			this.canBeSelected = b;
			this.dataType = dType;
		}
		
		public XPathNode getParent(){
			return parent;
		}
		
		public void setParent(XPathNode node){
			this.parent = node;
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public String getDisplayName() {
			return displayName;
		}

		public void setDisplayName(String displayName) {
			this.displayName = displayName;
		}

		public QName getDataType() {
			return dataType;
		}

		public void setDataType(QName dataType) {
			this.dataType = dataType;
		}

		public Boolean getCanBeSelected() {
			return canBeSelected;
		}

		public void setCanBeSelected(Boolean canBeSelected) {
			this.canBeSelected = canBeSelected;
		}

		public List<XPathNode> getChildren() {
			return children;
		}

		
		public void addChild(XPathNode child){
			if (this.children == null){
				this.children = new ArrayList<XPathNode>();
			}
			this.children.add(child);
			child.setParent(this);
		}
		
		public void removeAllChildren(){
			if (this.children!=null){
				this.children.clear();
			}
		}
	}
	
	class PropertiesTreeContententProvider implements ITreeContentProvider{
		SubProcessWrapper subProcessWrapper = null;
		boolean isFromExpression = true;
		
		PropertiesTreeContententProvider(boolean isFromExpression){
			this.isFromExpression = isFromExpression;
		}
		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.IContentProvider#dispose()
		 */
		public void dispose() {
			// TODO Auto-generated method stub
			
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
		 */
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
			if (newInput==null || !(newInput instanceof SubProcessWrapper)) return;
			subProcessWrapper = (SubProcessWrapper)newInput;
			
			//构建XPATH_NODE_PROCESS_VARIABLES子节点
			DataFieldListWrapper dfListWrapper = subProcessWrapper.getDataFieldsWrapper();
			if (dfListWrapper!=null && dfListWrapper.getChildren()!=null && dfListWrapper.getChildren().size()>0){
				List<Wrapper> children = dfListWrapper.getChildren();
				XPATH_NODE_PROCESS_VARIABLES.removeAllChildren();
				for (Wrapper child:children){
					XPathNode node = new XPathNode();
					node.setName(((DataFieldWrapper)child).getName());
					node.setDisplayName(((DataFieldWrapper)child).getDisplayName());
					node.setDataType(((DataFieldWrapper)child).getDataType());
					node.setCanBeSelected(true);
					XPATH_NODE_PROCESS_VARIABLES.addChild(node);
				}
			}
			//TODO 构建XPATH_NODE_ACTIVITY_VARIABLES子节点
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.ITreeContentProvider#getElements(java.lang.Object)
		 */
		public Object[] getElements(Object inputElement) {
			if (inputElement instanceof SubProcessWrapper){
				if (isFromExpression){
					return new Object[]{//From表达式可以有更多的选择
							XPATH_NODE_RUNTIME_CONTEXT,
							XPATH_NODE_WORKFLOW_SESSION,
							XPATH_NODE_CURRENT_PROCESS_INSTANCE,
							XPATH_NODE_CURRENT_ACTIVITY_INSTANCE,
							XPATH_NODE_PROCESS_VARIABLES
							//,
							//XPATH_NODE_ACTIVITY_VARIABLES
							};
				}else{
					return new Object[]{	
							//To表达式只能赋值该session变量或者流程实例变量或者活动实例变量
							XPATH_NODE_WORKFLOW_SESSION,
							XPATH_NODE_PROCESS_VARIABLES
							//,
							//XPATH_NODE_ACTIVITY_VARIABLES
							};
				}

			}
			return null;
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
		 */
		public Object[] getChildren(Object parentElement) {
			if (parentElement instanceof XPathNode){
				Object[] result = ((XPathNode)parentElement).getChildren().toArray();
				return result;
			}

			return null;
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)
		 */
		public Object getParent(Object element) {
			if (element instanceof XPathNode){
				return ((XPathNode)element).getParent();
			}
			return null;
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)
		 */
		public boolean hasChildren(Object element) {
			if (element instanceof XPathNode){
				return ((XPathNode)element).getChildren().size()>0?true:false;
			}
			return false;
		}
		
	}
}
